/**
 * GB28181服务监听程序
 */
const sip = require('sip');
const log4js = require('../data/log');
const logger = log4js.getLogger('sip');
const constants = require('../data/constants');
const dbHandler = require('../pipe/dbhandler');

// 命令都放在这里
const registerHandler = require('./handler/registerHandler');
const messageHandler = require('./handler/messageHandler');
const byeHandler = require('./handler/byeHandler');
const inviteHandler = require('./handler/inviteHandler');
const byeFactory = require('./factory/byeFactory');
const inviteFactory = require('./factory/inviteFactory');
const catalogFactory = require('./factory/catalogFactory');
const deviceinfoFactory = require('./factory/deviceinfoFactory');

/**
 * SIP服务端
 */
const sipServer = {
    running: false,
    stop: function () {
        if (this.running) {
            sip.stop();
        }
    },
    // 重启GB28181 服务
    restart: function (option) {
        constants.sip.option = option;
        if (!sipServer.running) {
            sipServer.start(option);
        }
    },
    /**
     * 启动 sip 服务端
     */
    start: function (option) {
        logger.info('[sip] GB28181启动参数:', option);
        constants.sip.option = option;
        let me = sipServer;

        sip.start({ port: option.sip_command_port, udp: constants.sip.udp, tcp: constants.sip.tcp,
            logger: {
                send: function (message) {
                    logger.info('[发送消息] =', message, 'via=', message.headers.via[0], message.headers.via.length > 1 ? message.headers.via[1] : '');
                },
                recv: function (rq, address) {
                    logger.info('[接收消息] =', rq, 'address=', address, 'via=', rq.headers.via[0], rq.headers.via.length > 1 ? rq.headers.via[1] : '');

                    // 不知道为什么有些消息在下面回调怎么取不到，临时放在这里处理
                    if (!rq.method) {
                        switch (rq.status) {
                            case 100:
                                logger.info('[接收消息] retry');
                                break;
                            case 200:
                                if (rq.headers.cseq.method === 'INVITE') {
                                    inviteHandler.handle(rq);
                                }
                                break;
                            case 400:
                                logger.error('[接收消息] bad request', rq);
                                break;
                        }
                    }
                }
            }
        }, function (rq) {
            const receiveUri = sip.parseUri(rq.headers.from.uri);
            const deviceId = receiveUri.user;
            try {
                dbHandler.loadDevice(deviceId).then((obj)=>{
                    if(obj) {
                        me.dataHandler(rq, deviceId).then(()=>{
                            logger.info(`[接收消息] deviceId=${deviceId} 消息分流处理完成`);
                        });
                    }else{
                        // logger.error(`[接收消息] 收到消息但数据库中没有设备信息:deviceId=${deviceId}`);
                        if(rq.method ==='REGISTER'){
                            registerHandler.handle(deviceId, rq).then(()=>{});
                        }
                    }
                });

            } catch (e) {
                logger.error(`[接收消息] 出现错误,deviceId=${deviceId}`, e);
            }
        });
    },
    // 消息分流处理
    dataHandler: async function (rq, deviceId) {
        if (!rq.method) {
            // method为空的放到logger的recv里处理了
        } else {
            if (rq.method === 'REGISTER') {
                await registerHandler.handle(deviceId, rq);
            } else if (rq.method === 'MESSAGE') {
                await messageHandler.handle(deviceId, rq);
            } else if (rq.method === 'ACK') {
                logger.info('[接收消息] TODO: Ack 消息未处理', rq);
            } else if (rq.method === 'BYE') {
                byeHandler.handle(rq);
            } else {
                logger.debug(`[接收消息] deviceId=${deviceId} TODO:尚不支持的方法:`, rq.method);
                sip.send(sip.makeResponse(rq, 405, 'Method Not Allowed'));
            }
        }
    },
    /**
     * 发invite消息，对外接口
     * @param media_ip
     * @param deviceId
     * @param channel
     * @param udpPort
     */
    invite:async  function (media_ip, deviceId, channel, udpPort) {
        try {
            const obj = await dbHandler.loadDevice(deviceId);
            if (obj) {
                let cmd = await inviteFactory.invite(media_ip, deviceId, channel, udpPort);
                if (cmd) {
                    sip.send(cmd);
                }
                return true;
            } else {
                logger.error(`[发送消息] deviceId=${deviceId} TODO:404 设备不存在`);
                return false;
            }
        } catch (e) {
            logger.error(`[发送消息] deviceId=${deviceId} 发invite指令异常`, e);
            return false;
        }
    },
    /**
     * 对外的接口
     * @param deviceId
     * @param channel
     * @returns {Promise<void>}
     */
    bye: function (deviceId, channel) {
        const cmd = byeFactory.generate(deviceId, channel);
        this.sendCmd(cmd);
    },
    /**
     * 请求设备列表
     * @param {*} deviceId
     */
    catalog: async function (deviceId) {
        const deviceInfo = await dbHandler.loadDevice(deviceId);
        const cmd = await catalogFactory.generate(deviceInfo);
        this.sendCmd(cmd);
    },
    deviceInfo: async function (deviceId) {
        const deviceInfo = await dbHandler.loadDevice(deviceId);
        const cmd = deviceinfoFactory.generate(deviceInfo);
        this.sendCmd(cmd);
    },
    sendCmd: function (cmd) {
        try {
            if (cmd) {
                logger.info('[发送消息] 内容:', cmd);
                sip.send(cmd);
            } else {
                logger.error('[发送消息] 指令生成异常');
            }
        } catch (e) {
            logger.error("[发送消息] 请求设备指令异常", cmd, e);
        }
    }
}

module.exports = sipServer;
